package nachos.threads;

/**
 * Schedules access to some sort of resource with limited access constraints. A
 * thread queue can be used to share this limited access among multiple
 * threads.
 *
 * <p>
 * Examples of limited access in Nachos include:
 *
 * <ol>
 * <li>the right for a thread to use the processor. Only one thread may run on
 * the processor at a time.
 *
 * <li>the right for a thread to acquire a specific lock. A lock may be held by
 * only one thread at a time.
 *
 * <li>the right for a thread to return from <tt>Semaphore.P()</tt> when the
 * semaphore is 0. When another thread calls <tt>Semaphore.V()</tt>, only one
 * thread waiting in <tt>Semaphore.P()</tt> can be awakened.
 *
 * <li>the right for a thread to be woken while sleeping on a condition
 * variable. When another thread calls <tt>Condition.wake()</tt>, only one
 * thread sleeping on the condition variable can be awakened.
 *
 * <li>the right for a thread to return from <tt>KThread.join()</tt>. Threads
 * are not allowed to return from <tt>join()</tt> until the target thread has
 * finished.
 * </ol>
 * <p>
 * All these cases involve limited access because, for each of them, it is not
 * necessarily possible (or correct) for all the threads to have simultaneous
 * access. Some of these cases involve concrete resources (e.g. the processor,
 * or a lock); others are more abstract (e.g. waiting on semaphores, condition
 * variables, or join).
 *
 * <p>
 * All thread queue methods must be invoked with <b>interrupts disabled</b>.
 */
public abstract class ThreadQueue {
    /**
     * 通知此线程队列：指定的线程正在等待访问
     * 只有当线程无法立即获得访问权限时，才应调用此方法
     * 比如当一个线程需要锁，但另外一个线程已经持有该锁
     *
     * <p>
     * 一个线程不能同时等待访问多个资源
     * 例如，等待锁的线程不能也在等待在处理器上运行
     * 如果线程正在等待锁，那么它应该处于休眠状态
     *
     * <p>
     * 但是，根据特定对象的不同，线程在访问另一个对象的同时等待访问一个对象可能是可以接受的
     * 例如，一个线程可能试图在持有另一个锁的同时获取一个锁
     * 但是请注意，在等待访问其他任何内容时，处理器不能被保持
     *
     * @param thread 正在等待访问的线程
     */
    public abstract void waitForAccess(KThread thread);

    /**
     * 通知此线程队列：另一个线程可以接收访问
     * 选择并返回下一个接收访问的线程，如果没有线程等待，则返回 null
     *
     * <p>
     * 如果受限的访问对象转移优先级，并且如果有其他线程等待访问，则它们将向返回的线程提供优先级
     *
     * @return 接收访问的下一个线程，如果没有线程等待，则返回 null
     */
    public abstract KThread nextThread();

    /**
     * 通知线程队列：一个线程已经收到访问权限，而不经过 request() 和 nextThread()
     * 例如，如果一个线程获得了一个没有其他线程在等待的锁，它应该调用这个方法
     *
     * <p>
     * 对于从 nextThread() 返回的线程，不应该调用该方法
     *
     * @param thread 已接收访问权限但未从 nextThread() 返回的线程
     */
    public abstract void acquire(KThread thread);

    /**
     * 打印所有等待访问的线程，不按特定顺序
     */
    public abstract void print();
}
